/* serialTest.c */
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdarg.h>
#include <string.h>
#include <termios.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>

/*打开指定的串口设备，并设置波特率*/
int mySerialOpen(const char *device, const int baud)
{
    struct termios options; // 串口配置参数
    speed_t myBaud;         // 波特率
    int status, fd;         // 状态和文件描述符

    // 根据传入的波特率参数设置相应的波特率
    switch (baud)
    {
    case 9600:
        myBaud = B9600;
        break;
    case 115200:
        myBaud = B115200;
        break;
    default:
        printf("不支持的波特率！\n");
        return -2;
    }

    // 打开串口设备
    if ((fd = open(device, O_RDWR | O_NOCTTY | O_NDELAY)) == -1)
    {
        printf("无法打开串口设备\n");
        return -1;
    }

    // 设置文件描述符的标志为读写模式
    fcntl(fd, F_SETFL, O_RDWR);

    // 获取当前串口配置
    tcgetattr(fd, &options);

    // 设置串口为原始模式，无特殊处理
    cfmakeraw(&options);
    // 设置输入波特率
    cfsetispeed(&options, myBaud);
    // 设置输出波特率
    cfsetospeed(&options, myBaud);

    // 清除标志位并设置数据格式
    options.c_cflag |= (CLOCAL | CREAD);
    options.c_cflag &= ~PARENB;                         // 无奇偶校验位
    options.c_cflag &= ~CSTOPB;                         // 1个停止位
    options.c_cflag &= ~CSIZE;                          // 清除数据位
    options.c_cflag |= CS8;                             // 设置为8位数据位
    options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); // 非规范模式，不执行输入处理
    options.c_oflag &= ~OPOST;                          // 输出处理

    // 设置读取时的超时和最小接收字符数
    options.c_cc[VMIN] = 0;
    options.c_cc[VTIME] = 100; // 10秒超时

    // 应用串口配置
    tcsetattr(fd, TCSANOW, &options);

    // 使用ioctl设置串口的DTR和RTS信号
    ioctl(fd, TIOCMGET, &status);
    status |= TIOCM_DTR;
    status |= TIOCM_RTS;
    ioctl(fd, TIOCMSET, &status);

    // 短暂延时
    usleep(10000); // 10毫秒延时

    return fd; // 返回文件描述符
}

/*向指定的串口设备发送字符串*/
void mySerialSendString(const int fd, const unsigned char *str, int len)
{
    int ret;

    ret = write(fd, str, len); // 发送串口数据
    if (ret == -1)
    {
        printf("串口发送失败！\n");
        exit(-1); // 发送失败，退出程序
    }
}

/*从指定的串口设备读取字符串*/
int mySerialReadString(const int fd, unsigned char *buffer)
{
    int n_read;

    n_read = read(fd, buffer, 32); // 读取串口数据
    if (n_read == -1)
    {
        printf("串口读取失败！\n");
        exit(-1); // 读取失败，退出程序
    }
}
